﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Xml.Linq;
//
using PerceptiveMCAPI.Types.Internal;
//
namespace PerceptiveMCAPI.Types
{
	public class campaignStatsOutput : Api_BaseOutput
	{
		public campaignStatsResults result { get; set; }
		public campaignStatsParms inputParms { get; private set; }
		// --------------------------------------------------------
		public campaignStatsOutput( campaignStatsInput input )
			: base( input )
		{
			inputParms = input.parms;
			result = new campaignStatsResults();
		}
		// --------------------------------------------------- tostring
		public override string ToString()
		{
			return string.Format( "emails_sent: {0}, unique_opens: {1}, unique_clicks: {2}, unsubscribes: {3}, abuse_reports: {4}, hard_bounces {5}, soft_bounces {6}",
				this.result.emails_sent, this.result.unique_opens, this.result.unique_clicks, this.result.unsubscribes,
				this.result.abuse_reports, this.result.hard_bounces, this.result.soft_bounces );
		}

		#region ================================================================== format setup

		// ---- serial
		internal void Format( string api_Request, string api_Response )
		{
			this.api_Request = api_Request;
			this.api_Response = api_Response;
			// ----------------------------------
			if ( this.api_OutputType == EnumValues.OutputType.JSON )
				outputJSON();
			else if ( this.api_OutputType == EnumValues.OutputType.XML )
				outputXML();
		}

		// ---- xmlrpc
		internal void Format( x_campaignStats rpcResult )
		{
			this.api_Request = EnumValues.NotSupplied;
			this.api_Response = EnumValues.NotSupplied;
			// ------------------------
			this.result = FormatResults( rpcResult );
		}

		#endregion

		#region ================================================================= Output

		// ---------------------------------------------------------- outputXML
		private void outputXML()
		{
			XElement xml = XElement.Parse( this.api_Response );
			Api_Error error = apiSerial.GetXmlOutputError( xml );
			if ( error != null )
			{
				this.api_ErrorMessages.Add( error );
				return;
			}
			// ------------------------------------ get values
			try
			{
				int it; DateTime dt;
				campaignStatsResults stats = new campaignStatsResults();
				//
				int.TryParse( xml.Element( "syntax_errors" ).Value, out it );
				stats.syntax_errors = it;
				int.TryParse( xml.Element( "hard_bounces" ).Value, out it );
				stats.hard_bounces = it;
				int.TryParse( xml.Element( "soft_bounces" ).Value, out it );
				stats.soft_bounces = it;
				int.TryParse( xml.Element( "unsubscribes" ).Value, out it );
				stats.unsubscribes = it;
				int.TryParse( xml.Element( "abuse_reports" ).Value, out it );
				stats.abuse_reports = it;
				int.TryParse( xml.Element( "forwards" ).Value, out it );
				stats.forwards = it;
				int.TryParse( xml.Element( "forwards_opens" ).Value, out it );
				stats.forwards_opens = it;
				int.TryParse( xml.Element( "opens" ).Value, out it );
				stats.opens = it;
				DateTime.TryParse( xml.Element( "last_open" ).Value, out dt );
				stats.last_open = dt;
				int.TryParse( xml.Element( "unique_opens" ).Value, out it );
				stats.unique_opens = it;
				int.TryParse( xml.Element( "clicks" ).Value, out it );
				stats.clicks = it;
				int.TryParse( xml.Element( "unique_clicks" ).Value, out it );
				stats.unique_clicks = it;
				int.TryParse( xml.Element( "users_who_clicked" ).Value, out it );
				stats.users_who_clicked = it;
				DateTime.TryParse( xml.Element( "last_click" ).Value, out dt );
				stats.last_click = dt;
				int.TryParse( xml.Element( "emails_sent" ).Value, out it );
				stats.emails_sent = it;
				//
				if ( xml.Element( "absplit" ).HasElements )
				{
					XElement absplit = xml.Element( "absplit" );
					//
					int.TryParse( absplit.Element( "bounces_a" ).Value, out it );
					stats.absplit.bounces_a = it;
					int.TryParse( absplit.Element( "forwards_a" ).Value, out it );
					stats.absplit.forwards_a = it;
					int.TryParse( absplit.Element( "abuse_reports_a" ).Value, out it );
					stats.absplit.abuse_reports_a = it;
					int.TryParse( absplit.Element( "unsubs_a" ).Value, out it );
					stats.absplit.unsubs_a = it;
					int.TryParse( absplit.Element( "recipients_click_a" ).Value, out it );
					stats.absplit.recipients_click_a = it;
					int.TryParse( absplit.Element( "forwards_opens_a" ).Value, out it );
					stats.absplit.forwards_opens_a = it;
					//
					int.TryParse( absplit.Element( "bounces_b" ).Value, out it );
					stats.absplit.bounces_b = it;
					int.TryParse( absplit.Element( "forwards_b" ).Value, out it );
					stats.absplit.forwards_b = it;
					int.TryParse( absplit.Element( "abuse_reports_b" ).Value, out it );
					stats.absplit.abuse_reports_b = it;
					int.TryParse( absplit.Element( "unsubs_b" ).Value, out it );
					stats.absplit.unsubs_b = it;
					int.TryParse( absplit.Element( "recipients_click_b" ).Value, out it );
					stats.absplit.recipients_click_b = it;
					int.TryParse( absplit.Element( "forwards_opens_b" ).Value, out it );
					stats.absplit.forwards_opens_b = it;
				}
				//
				if ( xml.Element( "timewarp" ).HasElements )
				{
					// need data to test
					//
					//IEnumerable<XElement> timewarp_array = xml.Element( "timewarp" ).Elements( "struct" );
					//foreach ( XElement entry in timewarp_array )
					//{
					//   campaignStatsResults.timewarp_stats tw = new campaignStatsResults.timewarp_stats();
					//   //
					//   int.TryParse( entry.Element( "opens" ).Value, out it );
					//   tw.opens = it;
					//   DateTime.TryParse( entry.Element( "last_open" ).Value, out dt );
					//   tw.last_open = dt;
					//   int.TryParse( entry.Element( "unique_opens" ).Value, out it );
					//   tw.unique_opens = it;
					//   int.TryParse( entry.Element( "clicks" ).Value, out it );
					//   tw.clicks = it;
					//   DateTime.TryParse( entry.Element( "last_click" ).Value, out dt );
					//   tw.last_click = dt;
					//   int.TryParse( entry.Element( "unique_clicks" ).Value, out it );
					//   tw.unique_clicks = it;
					//   int.TryParse( entry.Element( "bounces" ).Value, out it );
					//   tw.bounces = it;
					//   int.TryParse( entry.Element( "total" ).Value, out it );
					//   tw.total = it;
					//   int.TryParse( entry.Element( "sent" ).Value, out it );
					//   tw.sent = it;
					//   //
					//   stats.timewarp.Add( tw );
					//}
				}
				//
				this.result = stats;
			}
			catch ( Exception ex )
			{
				this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
			}
		}

		// ---------------------------------------------------------- outputJSON
		private void outputJSON()
		{
			JavaScriptSerializer jss = new JavaScriptSerializer();

			try
			{
				if ( this.api_Response.Contains( EnumValues.JSONErrorString ) )
				{
					Api_Error err = jss.Deserialize<Api_Error>( this.api_Response );
					this.api_ErrorMessages.Add( err );
				}
				else
				{
					x_campaignStats jsonResult = jss.Deserialize<x_campaignStats>( this.api_Response );
					this.result = FormatResults( jsonResult );
				}
			}
			catch ( Exception ex )
			{
				this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
			}
		}

		// -----------------------------
		private campaignStatsResults FormatResults( x_campaignStats x_results )
		{
			DateTime dt; int it;
			campaignStatsResults results = new campaignStatsResults();
			//
			results.syntax_errors = (int)x_results.syntax_errors;
			results.hard_bounces = (int)x_results.hard_bounces;
			results.soft_bounces = (int)x_results.soft_bounces;
			results.unsubscribes = (int)x_results.unsubscribes;
			results.abuse_reports = (int)x_results.abuse_reports;
			results.forwards = (int)x_results.forwards;
			results.forwards_opens = (int)x_results.forwards_opens;
			results.opens = (int)x_results.opens;
			DateTime.TryParse( x_results.last_open, out dt ); results.last_open = dt;
			results.unique_opens = x_results.unique_opens;
			results.clicks = x_results.clicks;
			results.unique_clicks = x_results.unique_clicks;
			DateTime.TryParse( x_results.last_click, out dt ); results.last_click = dt;
			results.users_who_clicked = (int)x_results.users_who_clicked;
			results.emails_sent = (int)x_results.emails_sent;
			// --------------------------- absplit
			IDictionary abdict = x_results.absplit as IDictionary;
			if ( abdict != null && abdict.Count > 0 )
			{
				// 'a' 
				int.TryParse( abdict["bounces_a"].ToString(), out it );
				results.absplit.bounces_a = it;
				int.TryParse( abdict["forwards_a"].ToString(), out it );
				results.absplit.forwards_a = it;
				int.TryParse( abdict["abuse_reports_a"].ToString(), out it );
				results.absplit.abuse_reports_a = it;
				int.TryParse( abdict["unsubs_a"].ToString(), out it );
				results.absplit.unsubs_a = it;
				int.TryParse( abdict["recipients_click_a"].ToString(), out it );
				results.absplit.recipients_click_a = it;
				int.TryParse( abdict["forwards_opens_a"].ToString(), out it );
				results.absplit.forwards_opens_a = it;
				// 'b' 
				int.TryParse( abdict["bounces_a"].ToString(), out it );
				results.absplit.bounces_a = it;
				int.TryParse( abdict["forwards_a"].ToString(), out it );
				results.absplit.forwards_a = it;
				int.TryParse( abdict["abuse_reports_a"].ToString(), out it );
				results.absplit.abuse_reports_a = it;
				int.TryParse( abdict["unsubs_a"].ToString(), out it );
				results.absplit.unsubs_a = it;
				int.TryParse( abdict["recipients_click_a"].ToString(), out it );
				results.absplit.recipients_click_a = it;
				int.TryParse( abdict["forwards_opens_a"].ToString(), out it );
				results.absplit.forwards_opens_a = it;
			}
			// --------------------------- timewarp
			if ( x_results.timewarp != null )
			{
				// TODO: Need data to test
			}
			//
			return results;
		}

		#endregion
	}
}
